home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / PASCAL / XTREEM01.ZIP / XTREEM.ASM < prev    next >
Encoding:
Assembly Source File  |  1995-04-18  |  36.2 KB  |  1,695 lines

  1. ;XTreem.asm - by Sean Palmer
  2. ; with a little help from:
  3. ;   Matt Pritchard, Bas Van Gaalen, Michael Abrash, Keld Hansen, Bresenham
  4. ; public domain
  5. ; credit me if you use any of this
  6.  
  7. ideal          ;needs TASM to assemble it.  I loathe MASM...
  8. model tpascal  ;my language of choice.  Change at your own risk!
  9. p386n          ;needs a 386 to run. Optimized for a 486 with VLB video.
  10.                ;Much of it also optimized for a Pentium, I hope...
  11.                ;Hard to tell since I don't have one!
  12.                ;Works in protected mode too
  13.  
  14. ;Be careful.. much of this doesn't have a lot of bounds checking.
  15. ;Give it valid numbers when at all possible!
  16. ;Clipping may come in a future version.
  17.  
  18. extrn yTab[564]:word  ;table for scan line start offsets
  19.  
  20. extrn segA000:word    ;video segment descriptor
  21.  
  22. extrn xRes:word       ;width of physical screen in pixels
  23. extrn yRes:word       ;height of physical screen in pixels
  24. extrn lxRes:word      ;width of virtual screen in pixels
  25. extrn lyRes:word      ;height of virtual screen in pixels
  26.  
  27. extrn lxBytes:word    ;width of virtual screen in bytes
  28. extrn pgBytes:word    ;size of a page in bytes
  29. extrn pgStart:dword   ;current write page offset in bytes
  30. extrn pgShown:dword   ;current display page offset in bytes
  31.  
  32. extrn oldMode:byte
  33.  
  34. attrPort   =3C0h      ;VGA Attribute Controller port
  35. miscOutPort=3C2h      ;VGA Misc Output Register
  36. seqPort    =3C4h      ;VGA Sequencer port
  37. gcPort     =3CEh      ;VGA Graphics Controller port
  38. crtcPort   =3D4h      ;CRT Controller port
  39. input1port =3DAh      ;CRT Input port #1
  40.  
  41.  
  42.  
  43. codeseg
  44.  
  45. dotMask     db 01h,02h,04h,08h
  46. lfPlaneMask db 0Fh,0Eh,0Ch,08h
  47. rtPlaneMask db 01h,03h,07h,0Fh
  48.  
  49.  
  50. public clear          ;clear screen 0
  51.  
  52. proc clear far color:byte
  53.   mov dx,seqPort      ;select all planes with map mask reg
  54.   les di,[pgStart]    ;set video segment
  55.   mov ax,0F02h
  56.   mov bl,[color]      ;gonna fill eax with color
  57.   out dx,ax
  58.   mov bh,bl
  59.   mov cx,[pgBytes]
  60.   shrd eax,ebx,16
  61.   shr cx,2            ;dword count
  62.   cld
  63.   mov ax,bx
  64.   rep stosd
  65.   ret
  66.   endp
  67.  
  68.  
  69. public textureColumn
  70. proc textureColumn far x:word,y:word,y2:word,                 \ ;dst coords (y2>=y)
  71.                        tx:dword,ty:dword,tx2:dword,ty2:dword, \ ;src coords
  72.                        tp:dword,tw:word   ;tp=^src bitmap, tw=src bitmap width
  73.  
  74.   mov bx,[x]
  75.   les di,[pgStart]
  76.   mov si,bx
  77.   and si,3
  78.   mov al,2
  79.   shr bx,2
  80.   mov ah,[dotMask+si]
  81.   mov dx,seqPort
  82.   add di,bx
  83.   out dx,ax
  84.   mov si,[y]
  85.   mov cx,[y2]
  86.   sub cx,si
  87.   add si,si
  88.   inc cx
  89.   add di,[yTab+si]
  90.   and ecx,0FFFFh    ;ecx=dest count
  91.   mov eax,[tx2]
  92.   sub eax,[tx]
  93.   cwde
  94.   idiv ecx
  95.   mov [tx2],eax     ;tx2=speedX
  96.   mov eax,[ty2]
  97.   sub eax,[ty]
  98.   cwde
  99.   idiv ecx
  100.   mov [ty2],eax     ;ty2=speedY
  101.   mov bx,[lxBytes]
  102.   mov ax,[word high ty]
  103.   mul bx
  104.   add ax,[word high tx]
  105.   mov [x],bx
  106.   xor si,si
  107.   lds si,[tp]
  108.   add si,ax
  109.   ret
  110.   endp
  111.  
  112.  
  113. ;takes about .008 sec to move a 320x200 page on my 486DX2/66 w/VLB video
  114. ;plus you get the benefits of your drawing routines never having to
  115. ;mess with any VGA registers!
  116. ;Your memory page should be laid out in a planar format, with sequential
  117. ;planes back-to-back
  118. ;This COULD be faster than direct screen writes depending on what kind of
  119. ;drawing you're doing and what kind of video you have. But it usually isn't.
  120.  
  121. public memBlt
  122.  
  123. proc memBlt far p:dword       ;blit a memory page to video ram
  124.   mov ax,ds
  125.   mov dx,seqPort
  126.   mov fs,ax
  127.   xor edi,edi
  128.   mov ax,0102h
  129.   les di,[pgStart]
  130.   out dx,ax
  131.   movzx ebx,[pgBytes]
  132.   inc dx
  133.   xor esi,esi
  134.   shr ebx,2                ;dwords
  135.   lds si,[p]
  136.   mov ecx,ebx
  137.   rep movs [dword es:edi],[dword ds:esi]
  138.   mov al,0010b
  139.   mov di,[word low fs:pgStart]
  140.   out dx,al
  141.   mov ecx,ebx
  142.   rep movs [dword es:edi],[dword ds:esi]
  143.   mov al,0100b
  144.   mov di,[word low fs:pgStart]
  145.   out dx,al
  146.   mov ecx,ebx
  147.   rep movs [dword es:edi],[dword ds:esi]
  148.   mov al,1000b
  149.   mov di,[word low fs:pgStart]
  150.   out dx,al
  151.   mov ecx,ebx
  152.   rep movs [dword es:edi],[dword ds:esi]
  153.   mov ax,fs
  154.   mov ds,ax
  155.   ret
  156.   endp
  157.  
  158. if 0
  159.  
  160. proc memBlt far p:dword       ;blit a packed memory page to unchained video ram
  161.   lgs di,[pgStart]
  162.   mov dx,seqPort
  163.   and esi,0FFFFh
  164.   mov ax,ds
  165.   mov cx,[pgBytes]
  166.   xor esi,esi
  167.   mov fs,ax
  168.   lds si,[p]
  169.   mov ax,0102h
  170.   shr cx,3               ;every 4th byte, loop unrolled once
  171.   out dx,ax
  172.   inc dx
  173. @@L0:
  174.   mov bh,[esi+12]
  175.   mov bl,[esi+8]
  176.   shl ebx,16
  177.   mov bh,[esi+4]
  178.   mov bl,[esi]
  179.   mov [gs:di],ebx
  180.   mov bh,[esi+28]
  181.   mov bl,[esi+24]
  182.   shl ebx,16
  183.   mov bh,[esi+20]
  184.   mov bl,[esi+16]
  185.   add si,32
  186.   mov [gs:di+4],ebx
  187.   add di,8
  188.   dec cx
  189.   jnz @@L0
  190.   mov di,[word low fs:pgStart]
  191.   mov al,2
  192.   movzx esi,[word low p]
  193.   mov cx,[fs:pgBytes]
  194.   inc esi
  195.   out dx,al
  196.   shr cx,3               ;every 4th byte, loop unrolled once
  197. @@L1:
  198.   mov bh,[esi+12]
  199.   mov bl,[esi+8]
  200.   shl ebx,16
  201.   mov bh,[esi+4]
  202.   mov bl,[esi]
  203.   mov [gs:di],ebx
  204.   mov bh,[esi+28]
  205.   mov bl,[esi+24]
  206.   shl ebx,16
  207.   mov bh,[esi+20]
  208.   mov bl,[esi+16]
  209.   add si,32
  210.   mov [gs:di+4],ebx
  211.   add di,8
  212.   dec cx
  213.   jnz @@L1
  214.   mov di,[word low fs:pgStart]
  215.   mov al,4
  216.   movzx esi,[word low p]
  217.   mov cx,[fs:pgBytes]
  218.   add esi,2
  219.   out dx,al
  220.   shr cx,3               ;every 4th byte, loop unrolled once
  221. @@L2:
  222.   mov bh,[esi+12]
  223.   mov bl,[esi+8]
  224.   shl ebx,16
  225.   mov bh,[esi+4]
  226.   mov bl,[esi]
  227.   mov [gs:di],ebx
  228.   mov bh,[esi+28]
  229.   mov bl,[esi+24]
  230.   shl ebx,16
  231.   mov bh,[esi+20]
  232.   mov bl,[esi+16]
  233.   add si,32
  234.   mov [gs:di+4],ebx
  235.   add di,8
  236.   dec cx
  237.   jnz @@L2
  238.   mov di,[word low fs:pgStart]
  239.   mov al,8
  240.   movzx esi,[word low p]
  241.   mov cx,[fs:pgBytes]
  242.   add esi,3
  243.   out dx,al
  244.   shr cx,3               ;every 4th byte, loop unrolled once
  245. @@L3:
  246.   mov bh,[esi+12]
  247.   mov bl,[esi+8]
  248.   shl ebx,16
  249.   mov bh,[esi+4]
  250.   mov bl,[esi]
  251.   mov [gs:di],ebx
  252.   mov bh,[esi+28]
  253.   mov bl,[esi+24]
  254.   shl ebx,16
  255.   mov bh,[esi+20]
  256.   mov bl,[esi+16]
  257.   add si,32
  258.   mov [gs:di+4],ebx
  259.   add di,8
  260.   dec cx
  261.   jnz @@L3
  262.   mov ax,fs
  263.   mov ds,ax
  264.   ret
  265.   endp
  266.  
  267. endif
  268.  
  269.  
  270. public plot
  271.  
  272. proc plot x:word,y:word,color:byte
  273.   les di,[pgStart]
  274.   mov si,[x]
  275.   mov bx,[y]
  276.   mov cx,si
  277.   add bx,bx
  278.   and si,3
  279.   shr cx,2
  280.   mov dx,seqPort
  281.   mov al,2              ;map mask register
  282.   mov ah,[dotMask+si]
  283.   add di,cx
  284.   out dx,ax             ;set map mask
  285.   add di,[yTab+bx]      ;di=byte offset
  286.   mov al,[color]
  287.   mov [es:di],al
  288.   ret
  289.   endp
  290.  
  291.  
  292. public scrn
  293.  
  294. proc scrn far x:word,y:word   ;returns color in al
  295.   les di,[pgStart]
  296.   mov si,[x]
  297.   mov bx,[y]
  298.   mov ax,si
  299.   add bx,bx
  300.   mov ah,al
  301.   shr si,2
  302.   mov al,4              ;read map select register in graphics controller
  303.   add di,si
  304.   and ah,3
  305.   add di,[yTab+bx]      ;di=byte offset
  306.   mov dx,gcPort
  307.   mov es,[segA000]
  308.   out dx,ax             ;set read map select
  309.   mov al,[es:di]
  310.   ret
  311.   endp
  312.  
  313.  
  314. public hLin
  315.  
  316. proc hLin x:word,x2:word,y:word,color:byte
  317.   mov si,[y]
  318.   les di,[pgStart]
  319.   add si,si
  320.   mov bx,[x]
  321.   mov cx,[x2]
  322.   cmp bx,cx
  323.   jl @@NOSWAP
  324.     xchg bx,cx
  325.   @@NOSWAP:
  326.   add di,[yTab+si]      ;di=base of scan line
  327.   mov si,bx
  328.   shr bx,2
  329.   and si,3
  330.   add di,bx             ;di=offset into video buffer
  331.   mov ah,[lfPlaneMask+si]
  332.   mov si,cx
  333.   mov al,2              ;map mask index
  334.   and si,3
  335.   shr cx,2
  336.   sub cx,bx             ;width in bytes-1
  337.   mov dx,seqPort
  338.   mov bh,[rtPlaneMask+si]
  339.   mov bl,[color]
  340.   jcxz @@ONE
  341.  
  342.   inc cx
  343.  
  344. ;  cmp ah,bh
  345. ;  je @@MIDDLE
  346.     cmp bh,0Fh
  347.     je @@LEFT
  348.       xchg ah,bh
  349.       dec cx
  350.       add di,cx
  351.       out dx,ax
  352.       mov ah,bh
  353.       mov [es:di],bl
  354.       sub di,cx
  355.     @@LEFT:
  356.     cmp ah,0Fh
  357.     je @@MIDDLE
  358.       out dx,ax
  359.       dec cx
  360.       mov [es:di],bl
  361.       mov ah,0Fh
  362.       inc di
  363.   @@MIDDLE:
  364.   out dx,ax
  365.   cmp cx,12
  366.   jae @@DWORDFILL
  367.   cmp cx,4
  368.   jae @@WORDFILL
  369.   jcxz @@EXIT
  370.   mov [es:di],bl
  371.   cmp cx,1
  372.   je @@EXIT
  373.   mov [es:di+1],bl
  374.   cmp cx,2
  375.   je @@EXIT
  376.   mov [es:di+2],bl
  377. @@EXIT:
  378.   ret
  379.  
  380. @@ONE:
  381.   and ah,bh
  382.   out dx,ax
  383.   mov [es:di],bl
  384.   ret
  385.  
  386. @@DWORDFILL:
  387.   cld
  388.   mov bh,bl
  389.   mov si,cx
  390.   shrd eax,ebx,16
  391.   mov ax,bx
  392.   xor cx,cx
  393.   sub cx,di
  394.   and ecx,3
  395.   sub si,cx
  396.   rep stosb           ;align to dword
  397.   mov cx,si
  398.   ror ecx,2
  399.   rep stosd
  400.   rol ecx,2
  401.   rep stosb           ;leftover bytes?
  402.   ret
  403.  
  404. @@WORDFILL:
  405.   cld
  406.   mov ah,bl
  407.   mov al,bl
  408.   test di,1
  409.   jz @@WORDALIGNED
  410.     mov [es:di],al
  411.     dec cx
  412.     inc di
  413.   @@WORDALIGNED:
  414.   shr cx,1
  415.   rep stosw           ;fill middle words
  416.   jnc @@EXIT
  417.   mov [es:di],bl
  418.   ret
  419.   endp
  420.  
  421.  
  422. public vLin
  423.  
  424. proc vLin far x:word,y:word,y2:word,color:byte
  425.   xor ebx,ebx
  426.   mov si,[x]
  427.   mov bx,si
  428.   and bx,3
  429.   mov di,[word low pgStart]
  430.   mov al,02h
  431.   mov ah,[dotMask+bx]
  432.   mov bx,[y]
  433.   add bx,bx
  434.   shr si,2
  435.   add di,si
  436.   mov dx,seqPort
  437.   add di,[yTab+bx]
  438.   mov cx,[y2]
  439.   out dx,ax
  440.   mov bx,di
  441.   mov di,[lxBytes]
  442.   sub cx,[y]
  443.   jnc @@OK
  444.     neg cx
  445.     neg di
  446.   @@OK:
  447.   mov al,[color]
  448.   push ds
  449.   mov ds,[word high pgStart]
  450.   inc cx
  451.   mov dx,cx
  452.   shr cx,2
  453.   and dx,3
  454.   jz @@X
  455.   mov [bx],al
  456.   add bx,di
  457.   dec dx
  458.   jz @@X
  459.   mov [bx],al
  460.   add bx,di
  461.   dec dx
  462.   jz @@X
  463.   mov [bx],al
  464.   add bx,di
  465.  @@X:
  466.   jcxz @@XIT
  467.   mov si,di
  468.   add si,si
  469.   xor edx,edx
  470.   mov dx,si
  471.   add dx,di
  472.  @@DOLINE:               ;unrolled * 4
  473.   mov [bx],al
  474.   mov [bx+di],al
  475.   mov [bx+si],al
  476.   mov [ebx+edx],al       ;it's still worth the prefix to get rid of the AGI's
  477.   add bx,si
  478.   add bx,si
  479.   dec cx
  480.   jnz @@DOLINE
  481.   pop ds
  482. @@XIT:
  483.   ret
  484.   endp
  485.  
  486.  
  487. public pane
  488.  
  489. proc pane x:word,y:word,x2:word,y2:word,color:byte
  490. local h:word,o:word
  491.   mov ax,[y2]
  492.   mov bx,[y]
  493.   sub ax,bx
  494.   jc @@EXIT
  495.   inc ax
  496.   mov [h],ax
  497.   les di,[pgStart]
  498.   cld
  499.   mov dx,seqPort
  500.   mov al,2
  501.   out dx,al               ;set up sequencer map mask
  502.   mov ax,[lxBytes]
  503.   mul bx
  504.   add di,ax               ;di=base of scan line
  505.   mov bx,[x]
  506.   mov dx,[x2]
  507.   mov si,bx
  508.   and si,3
  509.   shr bx,2                ;bx=horiz offset in bytes
  510.   mov al,[lfPlaneMask+si]
  511.   mov si,dx
  512.   and si,3
  513.   shr dx,2
  514.   sub dx,bx               ;dx=width in bytes
  515.   jc @@EXIT
  516.   add di,bx               ;di=offset into video buffer
  517.   mov bh,[rtPlaneMask+si]
  518.   mov [o],di
  519.   mov cx,dx
  520.   mov dx,seqport+1
  521.   test cx,cx
  522.   jnz @@LEFT
  523.   and al,bh               ;combine left & right bitmasks
  524.   jmp @@RIGHT
  525. @@LEFT:
  526.   inc cx
  527.   test al,al
  528.   jz @@CENTER2
  529.   out dx,al
  530.   mov al,[color]
  531.   mov si,[h]
  532. @@LEFTL:
  533.   mov [es:di],al
  534.   add di,[lxBytes]
  535.   dec si
  536.   jnz @@LEFTL
  537.   mov di,[o]
  538.   inc di
  539. @@CENTER2:
  540.   dec cx
  541.   add [o],cx
  542. @@CENTER:
  543.   jcxz @@EXIT
  544.   cmp bh,0Fh
  545.   je @@C2
  546.     dec cx
  547.     jz @@RIGHT2
  548. @@C2:
  549.   mov al,0Fh
  550.   out dx,al
  551.   mov al,[color]
  552.   mov ah,al
  553.   mov si,[h]
  554. @@CENTERL:
  555.   push cx
  556.   shr cx,1
  557.   rep stosw
  558.   jnc @@OVER
  559.     mov [es:di],al
  560.     inc di
  561.   @@OVER:
  562.   pop cx
  563.   add di,[lxBytes]
  564.   sub di,cx
  565.   dec si
  566.   jnz @@CENTERL
  567.   mov di,[o]
  568.   cmp bh,3
  569.   je @@EXIT
  570. @@RIGHT2:
  571.   mov al,bh
  572. @@RIGHT:
  573.   out dx,al
  574.   mov al,[color]
  575.   mov si,[h]
  576.   mov bx,[lxBytes]
  577. @@RIGHTL:
  578.   mov [es:di],al
  579.   add di,bx
  580.   dec si
  581.   jnz @@RIGHTL
  582. @@EXIT:
  583.   ret
  584.   endp
  585.  
  586. if 0
  587.  
  588. public line
  589.  
  590. proc line far x:word,y:word,x2:word,y2:word,color:byte
  591.   mov ax,[x]
  592.   mov bx,[x2]
  593.   mov cx,[y]
  594.   mov dx,[y2]
  595.   cmp ax,bx      ;make sure x>x2
  596.   jae @@NOSWAP
  597.     xchg ax,bx
  598.     xchg cx,dx
  599.   @@NOSWAP:
  600.   sub bx,ax
  601.   sub dx,cx
  602.   shl cx,1
  603.   les di,[pgStart]
  604. ;  add di,[yTab+cx]  ;illegal index mode!
  605.   mov cl,al
  606.   and cl,3
  607.   shr ax,2
  608.   add di,ax
  609.   mov ax,0102h
  610.   shl ah,cl
  611.  
  612.   mov bl,[color]
  613.   push ds
  614.   push bp
  615.  
  616.   @@HLOOP:
  617.     out dx,ax
  618.     dec cx
  619.     mov [di],bl
  620.     jz @@X
  621.     shr ah,1
  622.     jnz @@SAMEBYTE
  623.       dec di
  624.       mov ah,8
  625.     @@SAMEBYTE:
  626.     add bp,dx
  627.     jnc @@HLOOP
  628.     add di,si
  629.     jmp @@HLOOP
  630.  
  631.     out dx,ax
  632.   @@VLOOP:
  633.     dec cx
  634.     mov [di],bl
  635.     jz @@X
  636.     add di,si
  637.     add bp,dx
  638.     jnc @@VLOOP
  639.     shr ah,1
  640.     jnz @@VSAMEBYTE
  641.       dec di
  642.       mov ah,8
  643.     @@VSAMEBYTE:
  644.     out dx,ax
  645.     jmp @@VLOOP
  646.  
  647.   @@X:
  648.   pop bp
  649.   pop ds
  650.   ret
  651.   endp
  652.  
  653. else
  654.  
  655. extrn line:far
  656.  
  657. endif
  658.  
  659.  
  660. public curve
  661.  
  662. proc curve far x1:word,y1:word,x2:word,y2:word,x3:word,y3:word,color:word,steps:word
  663. local fx:dword,ex:dword,fy:dword,ey:dword
  664.  
  665.   mov ax,[x3]     ;adjust center point out *2 so curve fits the point
  666.   mov bx,[y3]
  667.   add ax,[x1]
  668.   add bx,[y1]
  669.   shr ax,1
  670.   shr bx,1
  671.   sub ax,[x2]
  672.   sub bx,[y2]
  673.   sub [x2],ax
  674.   sub [y2],bx
  675.  
  676.   movzx esi,[steps]
  677.   cmp si,2
  678.   jae @@OK
  679.     mov si,2
  680.   @@OK:
  681.   cmp si,4000h
  682.   jbe @@OK2
  683.     mov si,4000h
  684.   @@OK2:
  685.   mov edi,esi
  686.  
  687.   mov ax,[x2]     ;pre-calc important quantities
  688.   sub ax,[x1]
  689.   shl eax,17
  690.   mov edx,eax
  691.   sar edx,31
  692.   idiv edi
  693.   mov [ex],eax
  694.  
  695.   mov ax,[y2]
  696.   sub ax,[y1]
  697.   shl eax,17
  698.   mov edx,eax
  699.   sar edx,31
  700.   idiv edi
  701.   mov [ey],eax
  702.  
  703.   imul edi,edi
  704.  
  705.   mov ax,[x3]
  706.   sub ax,[x2]
  707.   sub ax,[x2]
  708.   add ax,[x1]
  709.   shl eax,16
  710.   mov edx,eax
  711.   sar edx,31
  712.   idiv edi
  713.   mov [fx],eax
  714.  
  715.   mov ax,[y3]
  716.   sub ax,[y2]
  717.   sub ax,[y2]
  718.   add ax,[y1]
  719.   shl eax,16
  720.   mov edx,eax
  721.   sar edx,31
  722.   idiv edi
  723.   mov [fy],eax
  724.  
  725.   dec esi
  726.   jz @@X
  727.  
  728.   @@LOOP:
  729.     push esi
  730.  
  731.     push [x3]
  732.     push [y3]
  733.  
  734.     mov eax,[fx]
  735.     imul eax,esi
  736.     add eax,[ex]
  737.     imul eax,esi
  738.     shr eax,16
  739.     add ax,[x1]
  740.     push ax
  741.     mov [x3],ax
  742.  
  743.     mov eax,[fy]
  744.     imul eax,esi
  745.     add eax,[ey]
  746.     imul eax,esi
  747.     shr eax,16
  748.     add ax,[y1]
  749.     push ax
  750.     mov [y3],ax
  751.  
  752.     push [word color]
  753.     call line
  754.     pop esi
  755.     dec si
  756.     jnz @@LOOP
  757.  
  758.   push [x3]
  759.   push [y3]
  760.   push [x1]
  761.   push [y1]
  762.   push [word color]
  763.   call line
  764. @@X:
  765.   ret
  766.   endp
  767.  
  768.  
  769. public circle      ;Keld Hansen gets credit for this cool Bresenham's circle
  770.                    ;implementation. I've tweaked it a bit for speed.
  771.  
  772. macro inplot ;expects cx=x,dx=y,ah=color,es=vidSeg,sequencer set to map mask reg
  773.              ;destroys al,cx,dx
  774.   push bx
  775.   push si
  776.   mov bx,dx
  777.   add bx,bx
  778.   mov si,cx
  779.   shr cx,2
  780.   and si,3
  781.   mov bx,[yTab+bx]      ;di=byte offset
  782.   mov al,[dotMask+si]
  783.   mov dx,seqPort+1
  784.   add bx,cx
  785.   out dx,al             ;set map mask
  786.   add bx,[word low pgStart]  ;this AGI will give time for sequencer to respond
  787.   pop si
  788.   mov [es:bx],ah
  789.   pop bx
  790.   endm
  791.  
  792. proc circle far xc:word,yc:word,r:word,c:byte
  793.   mov dx,seqPort
  794.   mov al,2                    ;map mask register
  795.   mov es,[word high pgStart]
  796.   out dx,al
  797.   xor si,si                   ;DeltaX := 0
  798.   mov di,[r]                  ;DeltaY := Radius
  799.   mov dx,3                    ;D := 3-2*Radius
  800.   sub dx,di
  801.   sub dx,di
  802.   push bp
  803.   mov ah,[c]
  804.   mov bx,[xc]                 ;bx := CenterX
  805.   mov bp,[yc]                 ;bp := CenterY
  806. @@L:
  807.   push dx
  808.  
  809.   lea cx,[bx+si]              ;cx := CenterX+Deltax
  810.   lea dx,[bp+di]              ;dx := CenterY+DeltaY
  811.   inplot
  812.  
  813.   lea cx,[bx+di]              ;cx := CenterX+DeltaY
  814.   lea dx,[bp+si]              ;dx := CenterY+Deltax
  815.   inplot
  816.  
  817.   neg di                      ;di := -DeltaY
  818.  
  819.   lea cx,[bx+si]              ;cx := CenterX+Deltax
  820.   lea dx,[bp+di]              ;dx := CenterY-DeltaY
  821.   inplot
  822.  
  823.   lea cx,[bx+di]              ;cx := CenterX-DeltaY
  824.   lea dx,[bp+si]              ;dx := CenterY+Deltax
  825.   inplot
  826.  
  827.   neg si                      ;si := -Deltax
  828.  
  829.   lea cx,[bx+di]              ;cx := CenterX-DeltaY
  830.   lea dx,[bp+si]              ;dx := CenterY-Deltax
  831.   inplot
  832.  
  833.   lea cx,[bx+si]              ;cx := CenterX-Deltax
  834.   lea dx,[bp+di]              ;dx := CenterY-DeltaY
  835.   inplot
  836.  
  837.   neg di                      ;di := DeltaY
  838.  
  839.   lea cx,[bx+si]              ;cx := CenterX-Deltax
  840.   lea dx,[bp+di]              ;dx := CenterY+DeltaY
  841.   inplot
  842.  
  843.   lea cx,[bx+di]              ;cx := CenterX+DeltaY
  844.   lea dx,[bp+si]              ;dx := CenterY-Deltax
  845.   inplot
  846.  
  847.   pop dx                      ;Retrieve saved reg
  848.  
  849.   push ax                     ;preserve color
  850.   mov ax,si
  851.   mov cx,6
  852.   test dh,dh                  ;if D < 0
  853.   js @@DLT0
  854.     add cx,4
  855.     sub ax,di                   ;D+=4*(Deltax-DeltaY)+10
  856.     dec di                      ;DeltaY--
  857.   @@DLT0:                     ;else
  858.   lea ax,[eax*4+ecx]            ;D+=4*Deltax+6
  859.   add dx,ax
  860.   inc si                      ;Deltax++
  861.   pop ax
  862.   cmp si,di
  863.   jle @@L
  864.   pop bp
  865.   ret
  866.   endp
  867.  
  868.  
  869. public calcEdge
  870.  
  871. proc calcEdge near x:word,y:word,x2:word,y2:word,tbl:dword
  872.   les di,[tbl]
  873.   mov ax,[y]
  874.   mov bx,[y2]
  875.   xor ecx,ecx
  876.   mov cx,[x]
  877.   mov dx,[x2]
  878.   cmp ax,bx
  879.   je @@X
  880.   jl @@NOSWAP
  881.     add di,2
  882.     xchg ax,bx
  883.     xchg cx,dx
  884.   @@NOSWAP:
  885.   lea di,[eax*4+edi]  ;es:di now points to table[minY,dir]
  886.   sub bx,ax
  887.   mov si,ax       ;si=y
  888.   sub dx,cx
  889.   xor al,al
  890.   mov ah,dl
  891.   sar dx,8
  892.   idiv bx
  893.   inc bx          ;bx=ySteps
  894.   cwde            ;eax=xStep
  895.   shl ecx,8       ;ecx=x
  896.   mov cl,80h      ;pre-round
  897.   @@L:
  898.     test si,si
  899.     js @@OFFSCREEN
  900.     cmp si,[lyRes]
  901.     jge @@X
  902.      ror ecx,8
  903.     shld edx,ecx,24
  904.     test dx,dx
  905.     js @@LEFT
  906.     cmp dx,[lxRes]
  907.     jge @@RIGHT
  908.     @@OK:
  909.     mov [es:di],cx
  910.     rol ecx,8
  911.     @@OFFSCREEN:
  912.     add ecx,eax
  913.     add di,4
  914.     inc si
  915.     dec bx
  916.     jnz @@L
  917.   @@X:
  918.   ret
  919.  
  920.     @@RIGHT:
  921.       mov dx,[lxRes]
  922.       dec dx
  923.       jmp @@OK
  924.     @@LEFT:
  925.       xor dx,dx
  926.       jmp @@OK
  927.  
  928.   endp
  929.  
  930. public rowList
  931.  
  932. proc rowList far startY:word,count:word,tbl:dword,color:byte
  933.   cmp [count],0
  934.   jz @@X
  935.   mov ax,[startY]
  936.   shl ax,2
  937.   add [word low tbl],ax
  938.   @@L:
  939.     les di,[tbl]
  940.     mov bx,[es:di]
  941.     mov cx,[es:di+2]
  942.     mov dx,[lxRes]       ;clip against sides
  943.     cmp bx,dx
  944.     jge @@SKIP
  945.     test cx,cx
  946.     js @@SKIP
  947.     test bx,bx
  948.     jns @@LOK
  949.       xor bx,bx
  950.     @@LOK:
  951.     cmp cx,dx
  952.     jl @@ROK
  953.       mov cx,dx
  954.     @@ROK:
  955.  
  956.     mov si,[startY]       ;this is pretty much just the hlin code
  957.     les di,[pgStart]      ;but replicated inline to avoid function
  958.     add si,si             ;call overhead
  959.     cmp bx,cx
  960.     jl @@NOSWAP
  961.       xchg bx,cx
  962.     @@NOSWAP:
  963.     add di,[yTab+si]      ;di=base of scan line
  964.     mov si,bx
  965.     and si,3
  966.     shr bx,2
  967.     add di,bx             ;di=offset into video buffer
  968.     mov ah,[lfPlaneMask+si]
  969.     mov si,cx
  970.     mov al,2              ;map mask index
  971.     and si,3
  972.     shr cx,2
  973.     sub cx,bx             ;width in bytes-1
  974.     mov dx,seqPort
  975.     mov bh,[rtPlaneMask+si]
  976.     mov bl,[color]
  977.     jcxz @@ONE
  978.     inc cx
  979.     cmp bh,0Fh
  980.     je @@LEFT
  981.       xchg ah,bh
  982.       dec cx
  983.       out dx,ax
  984.       add di,cx
  985.       mov ah,bh
  986.       mov [es:di],bl
  987.       sub di,cx
  988.     @@LEFT:
  989.     cmp ah,0Fh
  990.     je @@MIDDLE
  991.       out dx,ax
  992.       dec cx
  993.       mov [es:di],bl
  994.       mov ah,0Fh
  995.       inc di
  996.     @@MIDDLE:
  997.     out dx,ax
  998. ;    cmp cx,12
  999. ;    jae @@DWORDFILL  ;dwords end up slowing it down in most cases
  1000.     cmp cx,4
  1001.     jae @@WORDFILL
  1002.     jcxz @@SKIP
  1003.     mov [es:di],bl
  1004.     cmp cx,1
  1005.     je @@SKIP
  1006.     mov [es:di+1],bl
  1007.     cmp cx,2
  1008.     je @@SKIP
  1009.     mov [es:di+2],bl
  1010.     jmp @@SKIP
  1011.  
  1012.   @@ONE:
  1013.     and ah,bh
  1014.     out dx,ax
  1015.     mov [es:di],bl
  1016.     jmp @@SKIP
  1017.  
  1018. ;  @@DWORDFILL:
  1019. ;    cld
  1020. ;    mov bh,bl
  1021. ;    shrd eax,ebx,16
  1022. ;    mov ax,bx
  1023. ;    mov si,cx
  1024. ;    xor cx,cx
  1025. ;    sub cx,di
  1026. ;    and ecx,3
  1027. ;    sub si,cx
  1028. ;    rep stosb           ;align to dword
  1029. ;    mov cx,si
  1030. ;    ror ecx,2
  1031. ;    rep stosd
  1032. ;    rol ecx,2
  1033. ;    rep stosb           ;leftover bytes?
  1034. ;    jmp @@SKIP
  1035.  
  1036.   @@WORDFILL:
  1037.     cld
  1038.     mov ah,bl
  1039.     mov al,bl
  1040.     test di,1
  1041.     jz @@WORDALIGNED
  1042.       mov [es:di],al
  1043.       dec cx
  1044.       inc di
  1045.     @@WORDALIGNED:
  1046.     shr cx,1
  1047.     rep stosw           ;fill middle words
  1048.     jnc @@SKIP
  1049.     mov [es:di],bl
  1050.  
  1051.   @@SKIP:
  1052.     add [word low tbl],4
  1053.     inc [startY]
  1054.     dec [count]
  1055.     jnz @@L
  1056.   @@X:
  1057.   ret
  1058.   endp
  1059.  
  1060. ;------------------------------------------------------------------------
  1061.  
  1062. ;drawSprite takes a pointer to a custom sprite data structure
  1063. ;which must be produced in this format:
  1064. ;
  1065. ; word    width in bytes
  1066. ; word    height of sprite data (must match # of 0 commands in each plane)
  1067. ; word    horz offset of sprite center from upper left
  1068. ; word    vert " "
  1069. ;
  1070. ;this is followed by 4 sets of these commands, one for each plane:
  1071. ;
  1072. ;         0  move to start of next row
  1073. ;   1...127  draw this many bytes that follow in sprite data
  1074. ;  -1..-128  skip over this many screen bytes
  1075. ;
  1076. ;All rows must be accounted for in each plane, but rows don't have
  1077. ;to have data for the entire width of the sprite.
  1078. ;This allows for oddly-shaped/semi-transparent objects like text
  1079. ;as well as solid rectangular objects. As written, it's fast
  1080. ;enough that a separate routine to draw non-transparent images
  1081. ;is unnecessary (virtually no speed gain)
  1082.  
  1083. ;This format is peculiar because each set of commands describes how
  1084. ;to draw one plane of the sprite. Planes are left to right, and are
  1085. ;interlaced. (yes unchained modes are peculiar.)  This is the fastest
  1086. ;known way to get sprite data onto the screen so if you want speed,
  1087. ;figure this format out and live with it. Or, be slow--see if I care.
  1088.  
  1089. ;for a 12x2 object, here is the order it is stored and gets drawn:
  1090. ;(letters are planes, numbers are byte index into the plane)
  1091. ; a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3
  1092. ; a4 b4 c4 d4 a5 b5 c5 d5 a6 b6 c6 d6
  1093.  
  1094. ;let's say you're trying to draw this simple shape:
  1095. ;       ##@
  1096. ;      #@#@#
  1097. ;       @# #
  1098.  
  1099. ;plane 12341
  1100.  
  1101. ;it's 5x3. The first plane has two bytes, the rest one.
  1102. ;so the resulting file needed to draw this shape would consist of
  1103. ;the following hex bytes (# is color 33 hex, @ is color 44 hex)
  1104.  
  1105. ; width                  05 00
  1106. ; height                 03 00
  1107. ; h ofs                  02 00
  1108. ; v ofs                  01 00
  1109. ; plane one   row one    00            first and fifth column data
  1110. ;             row two    02 33 33 00
  1111. ;             row three  FF 01 33 00   (ff=-1, or 1 transparent byte)
  1112. ; plane two   row one    01 33 00      second column data
  1113. ;             row two    01 44 00
  1114. ;             row three  01 44 00
  1115. ; plane three row one    01 33 00      third column data
  1116. ;             row two    01 33 00
  1117. ;             row three  01 33 00
  1118. ; plane four  row one    01 44 00      fourth column data
  1119. ;             row two    01 44 00
  1120. ;             row three  00
  1121.  
  1122. ;This example is a contrived (and small) one. Large ones turn out
  1123. ;much better in actual practice.
  1124.  
  1125. ;the sprite, when drawn, is not clipped. If drawing partially offscreen
  1126. ;it is expected that you will have extra virtual display space surrounding
  1127. ;the display window.
  1128.  
  1129. public drawSprite
  1130.  
  1131. proc drawSprite far sprite:dword,x:word,y:word
  1132.   cld
  1133.  
  1134.   mov ax,[x]
  1135.   mov cx,ax
  1136.   shr ax,2           ;bytes
  1137.   les bx,[pgStart]   ;calc offset using active page
  1138.   mov di,[y]
  1139.   add di,di
  1140.   add bx,[yTab+di]
  1141.   add bx,ax          ;bx=offset into video ram of top left of sprite
  1142.  
  1143.   mov si,[lxBytes]
  1144.   shl esi,16         ;esihi=bytes per scan line
  1145.  
  1146.   push ds
  1147.   lds si,[sprite]
  1148.   push ebp
  1149.  
  1150.   shl ebx,16         ;ebxhi=dst reloader
  1151.   mov ax,[si+2]      ;ax=sprite height
  1152.   shl eax,16         ;eaxhi=sprite height reloader
  1153.   and cl,3
  1154.   mov ax,0102h
  1155.   shl ah,cl          ;ah=current plane
  1156.   add si,8           ;skip size/origin data
  1157.   mov edx,30000h+seqPort   ;edxhi=planes of sprite data to go-1
  1158.   @@PLANE:
  1159.     out dx,ax        ;set sequencer map mask
  1160.     shld edi,ebx,16  ;di=dst
  1161.     shld ebp,eax,16  ;bp=sprite height
  1162.     mov bx,di        ;save dst
  1163.     @@ROW:
  1164.       shld ecx,esi,16
  1165.       add bx,cx
  1166.       db 0A9h        ;test ax,imm16 instr to skip next 2 byte instr
  1167.       @@SKIP:
  1168.         sub di,cx    ;bump di by -count (2 byte instr)
  1169.       @@DATA:
  1170.         movsx cx,[si]
  1171.         inc si
  1172.         test cx,cx
  1173.         js @@SKIP
  1174.         jz @@NEXTROW
  1175.         movzx ecx,cx ;zero ecxhi
  1176.         ror ecx,2    ;save lo 2 bits in ecxhi
  1177.         rep movsd    ;fast dword move..doesn't affect ecxhi
  1178.         rol ecx,2    ;retrieve saved bits
  1179.         jz @@DATA    ;anything to do?
  1180.         rep movsb    ;finish off remaining bytes
  1181.         jmp @@DATA
  1182.       @@NEXTROW:
  1183.       mov di,bx
  1184.       dec bp
  1185.       jnz @@ROW
  1186.     shl ah,1
  1187.     test ah,10h        ;did plane wrap to next byte?
  1188.     jz @@NOPLANEWRAP
  1189.       add ebx,10000h
  1190.       mov ah,1
  1191.     @@NOPLANEWRAP:
  1192.     sub edx,10000h     ;any more planes?
  1193.     jnc @@PLANE
  1194.   pop ebp
  1195.   pop ds
  1196.   ret
  1197.   endp
  1198.  
  1199. ;drawTile takes a pointer to a special record format too. It's:
  1200. ;  word  width in bytes
  1201. ;  word  height
  1202. ;followed by 4 planes of packed bytes (first is leftmost)
  1203. ;this is a little faster than drawSprite for non-transparent objects
  1204. ;this isn't clipped either. See drawSprite for details.
  1205.  
  1206. public drawTile
  1207.  
  1208. proc drawTile far tile:dword,x:word,y:word
  1209.   cld
  1210.   mov ax,[x]
  1211.   mov cx,ax
  1212.   shr ax,2           ;bytes
  1213.   les si,[pgStart]   ;calc offset using active page
  1214.   mov bx,[y]
  1215.   shl bx,1
  1216.   add si,[yTab+bx]
  1217.   add si,ax          ;si=offset into video ram of top left of tile
  1218.   shl esi,16         ;esihi=dest reloader
  1219.  
  1220.   mov bx,[lxBytes]
  1221.  
  1222.   push ds
  1223.   lds si,[sprite]
  1224.   push ebp
  1225.  
  1226.   mov ax,[si]        ;width in bytes
  1227.   sub bx,ax
  1228.   rol ebx,16
  1229.   mov bx,ax
  1230.   rol ebx,16         ;ebxhi=width reloader, bx=offset to next scan line
  1231.  
  1232.   mov ax,[si+2]      ;height
  1233.   add si,4           ;skip size/origin data
  1234.   shl eax,16         ;eaxhi=tile height reloader
  1235.   and cl,3
  1236.   mov ax,0102h
  1237.   mov edx,30000h+seqPort   ;edxhi=planes of sprite data to go-1
  1238.   shl ah,cl          ;ah=current plane
  1239.   @@PLANE:
  1240.     out dx,ax        ;set sequencer map mask
  1241.     shld edi,esi,16  ;di=dest
  1242.     shld ebp,eax,16  ;bp=height
  1243.     xor cx,cx
  1244.     @@ROW:
  1245.       shld ecx,ebx,16 ;reload count
  1246.       ror ecx,2
  1247.       rep movsd
  1248.       rol ecx,2
  1249.       rep movsb
  1250.       add di,bx
  1251.       dec bp
  1252.       jnz @@ROW
  1253.     shl ah,1
  1254.     test ah,10h        ;did plane wrap to next byte?
  1255.     jz @@NOPLANEWRAP
  1256.       add esi,10000h
  1257.       mov ah,1
  1258.     @@NOPLANEWRAP:
  1259.     sub edx,10000h     ;any more planes?
  1260.     jnc @@PLANE
  1261.   pop ebp
  1262.   pop ds
  1263.   ret
  1264.   endp
  1265.  
  1266. if 0
  1267.  
  1268.  
  1269. public CopyRect
  1270.  
  1271. proc CopyRect far srcStartX:word,srcStartY:word,   \
  1272.                   srcEndX:word,srcEndY:word,       \
  1273.                   dstStartX:word,dstStartY:word,       \
  1274.                   srcPageBase:word,dstPageBase:word, \
  1275.                   srcBmpWidth:word,dstBmpWidth:word
  1276. local srcNext:word,dstNext:word, \
  1277.       height:word,rectAddrWidth:word
  1278.   push ds
  1279.  
  1280.   cld
  1281.   mov dx,gcPort       ;set the bit mask to select all bits
  1282.   mov ax,8            ; from the latches and none from
  1283.   out dx,ax           ; the CPU, so that we can write the
  1284.                       ; latch contents directly to memory
  1285.   mov es,[segA000]
  1286.   mov ax,[dstBmpWidth]
  1287.   shr ax,2             ;convert to width in addresses
  1288.   mul [dstStartY]     ;top dst rect scan line
  1289.   mov di,[dstStartX]
  1290.   shr di,2             ;X/4 = offset of first dst rect pixel in scan line
  1291.   add di,ax            ;offset of first dst rect pixel in page
  1292.   add di,[dstPageBase] ;offset of first dst rect pixel in display memory
  1293.   mov ax,[srcBmpWidth]
  1294.   shr ax,2             ;convert to width in addresses
  1295.   mul [srcStartY]   ;top src rect scan line
  1296.   mov si,[srcStartX]
  1297.   mov bx,si
  1298.   shr si,2             ;X/4 = offset of first src rect pixel in scan line
  1299.   add si,ax            ;offset of first src rect pixel in page
  1300.   add si,[srcPageBase]  ;offset of first src rect pixel in display memory
  1301.   and bx,0003h                   ;look up left edge plane mask to clip
  1302.   mov ah,[lfPlaneMask+bx]
  1303.   mov bx,[srcEndX]
  1304.   and bx,0003h                   ;look up right edge plane mask to clip
  1305.   mov al,[rtPlaneMask+bx]
  1306.   mov bx,ax                      ;put the masks in BX
  1307.  
  1308.   mov cx,[srcEndX]   ;calculate # of addresses across
  1309.   mov ax,[srcStartX] ; rect
  1310.   cmp cx,ax
  1311.   jle @@CopyDone        ;skip if 0 or negative width
  1312.   dec cx
  1313.   and ax,not 011b
  1314.   sub cx,ax
  1315.   shr cx,2       ;# of addresses across rectangle to copy - 1
  1316.   jnz @@MasksSet ;there's more than one address to draw
  1317.   and bh,bl      ;there's only one address, so combine the left
  1318.                  ; and right edge clip masks
  1319. @@MasksSet:
  1320.   mov ax,[srcEndY]
  1321.   sub ax,[srcStartY]  ;AX = height of rectangle
  1322.   jle @@CopyDone         ;skip if 0 or negative height
  1323.   mov [Height],ax
  1324.   mov ax,[dstBmpWidth]
  1325.   shr ax,2    ;convert to width in addresses
  1326.   sub ax,cx   ;distance from end of one dst scan line to
  1327.   dec ax      ;start of next
  1328.   mov [dstNext],ax
  1329.   mov ax,[srcBmpWidth]
  1330.   shr ax,2    ;convert to width in addresses
  1331.   sub ax,cx   ;distance from end of one src scan line to
  1332.   dec ax      ; start of next
  1333.   mov [srcNext],ax
  1334.   mov [RectAddrWidth],cx ;remember width in addresses - 1
  1335.   mov dx,seqPort ;point to Sequence Controller Data reg
  1336.   mov al,2       ;map mask reg
  1337.   out dx,al
  1338.   inc dx      ;primed and ready
  1339.   mov ax,es   ;DS=ES=screen segment for MOVS
  1340.   mov ds,ax
  1341. @@CopyRowsLoop:
  1342.   mov cx,[RectAddrWidth] ;width across - 1
  1343.   mov al,bh   ;put left-edge clip mask in AL
  1344.   out dx,al   ;set the left-edge plane (clip) mask
  1345.   movsb       ;copy the left edge (pixels go through latches)
  1346.   dec cx      ;count off left edge address
  1347.   js @@CopyLoopBottom ;that's the only address
  1348.   jz @@DoRightEdge ;there are only two addresses
  1349.   mov al,00fh ;middle addresses are drawn 4 pixels at a pop
  1350.   out dx,al   ;set the middle pixel mask to no clip
  1351.   rep movsb   ;draw the middle addresses four pixels apiece
  1352.               ; (pixels copied through latches)
  1353. @@DoRightEdge:
  1354.   mov al,bl   ;put right-edge clip mask in AL
  1355.   out dx,al   ;set the right-edge plane (clip) mask
  1356.   movsb       ;draw the right edge (pixels copied through latches)
  1357. @@CopyLoopBottom:
  1358.   add si,[srcNext] ;point to the start of next src & dst lines
  1359.   add di,[dstNext]
  1360.   dec [Height]     ;count down scan lines
  1361.   jnz @@CopyRowsLoop
  1362. @@CopyDone:
  1363.   mov dx,gcPort+1     ;restore the bit mask to its default,
  1364.   mov al,0ffh         ; which selects all bits from the CPU
  1365.   out dx,al           ; and none from the latches (the GC
  1366.                       ; Index still points to Bit Mask)
  1367.   pop ds
  1368.   ret
  1369.   endp
  1370. endif
  1371.  
  1372. ;--------------------------------------------------------------------
  1373.  
  1374. dacReadIndex   =3C7h;
  1375. dacWriteIndex  =3C8h;
  1376. dacDataRegister=3C9h;
  1377.  
  1378.  
  1379. public setColor
  1380.  
  1381. proc setColor far color:byte,r:byte,g:byte,b:byte
  1382.  mov dx,dacWriteIndex
  1383.  mov al,[color]
  1384.  out dx,al
  1385.  inc dx
  1386.  mov al,[r]
  1387.  out dx,al
  1388.  mov al,[g]
  1389.  out dx,al
  1390.  mov al,[b]
  1391.  out dx,al
  1392.  ret
  1393.  endp
  1394.  
  1395.  
  1396. public getColor
  1397.  
  1398. proc getColor far color:byte  ;returns longint color in ax,dx
  1399.  mov dx,dacReadIndex
  1400.  mov al,[color]
  1401.  out dx,al
  1402.  add dx,2
  1403.  in al,dx
  1404.  mov bl,al
  1405.  in al,dx
  1406.  mov ah,al
  1407.  in al,dx
  1408.  movzx dx,bl
  1409.  ret
  1410.  endp
  1411.  
  1412.  
  1413. public setPalette
  1414.  
  1415. proc setPalette far color:byte,num:word,rgb:dword
  1416.  mov cx,[num]
  1417.  jcxz @@X
  1418.  lea cx,[ecx+ecx*2]   ;quick 386 mul by 3
  1419.  cld
  1420.  mov dx,dacWriteIndex
  1421.  mov al,[color]
  1422.  out dx,al
  1423.  inc dx
  1424.  push ds
  1425.  lds si,[rgb]
  1426.  rep outsb
  1427. ;@@L: outsb      ;replace "rep outsb" with this if it's too fast
  1428. ; dec cx         ;for your vga card
  1429. ; jnz @@L
  1430.  pop ds
  1431. @@X:
  1432.  ret
  1433.  endp
  1434.  
  1435.  
  1436. public getPalette
  1437.  
  1438. proc getPalette far color:byte,num:word,rgb:dword
  1439.  mov cx,[num]
  1440.  jcxz @@X
  1441.  lea cx,[ecx+ecx*2]    ;quick 386 mul by 3
  1442.  les di,[rgb]
  1443.  cld
  1444.  mov dx,dacReadIndex
  1445.  mov al,[color]
  1446.  out dx,al
  1447.  add dx,2
  1448.  rep insb
  1449. ;@@L: insb      ;replace "rep insb" with this if it's too fast
  1450. ;  dec cx       ;for your vga card
  1451. ;  jnz @@L
  1452. @@X:
  1453.  ret
  1454.  endp
  1455.  
  1456. ;--------------------------------------------------------------------
  1457.  
  1458.  
  1459. public setWritePage
  1460.  
  1461. proc setWritePage far adr:word
  1462.   mov ax,[adr]
  1463.   mov [word low pgStart],ax
  1464.   ret
  1465.   endp
  1466.  
  1467.  
  1468. public setDisplayPage
  1469.  
  1470. proc setDisplayPage far adr:word
  1471.   mov bx,[adr]
  1472.   mov [word low pgShown],bx    ;save display page start address
  1473. ;  shr bx,1                     ;set display start address
  1474.   mov dx,CRTCPort
  1475.   mov al,0Ch                   ;hi byte
  1476.   mov ah,bh
  1477.   cli
  1478.   out dx,ax
  1479.   inc ax                       ;lo byte
  1480.   mov ah,bl
  1481.   out dx,ax
  1482.   sti
  1483.   mov dx,input1Port
  1484. @@L:
  1485.   in al,dx
  1486.   test al,8
  1487.   jz @@L                       ;wait for vertical retrace
  1488.   ret
  1489.   endp
  1490.  
  1491. ;scrolls the window so that x,y is the upper-left corner
  1492. ;x must be <=lxRes-xRes, y must be <=lyRes-yRes
  1493.  
  1494. public setWindow
  1495.  
  1496. proc setWindow far x:word,y:word
  1497.   mov bx,[y]
  1498.   shl bx,1
  1499.   mov ax,[yTab+bx]
  1500.   mov bx,[x]
  1501.   mov cl,bl
  1502.   shr bx,2
  1503.   add bx,[word low pgStart]
  1504.   add bx,ax         ;bx=ofs of top left corner
  1505.   mov [word low pgShown],bx  ;save display page start address
  1506. ;  shr bx,1          ;set display start address
  1507.   mov dx,CRTCPort
  1508.   mov al,0Ch        ;hi byte
  1509.   mov ah,bh
  1510.   cli
  1511.   out dx,ax
  1512.   inc ax            ;lo byte
  1513.   mov ah,bl
  1514.   out dx,ax         ;now we're ready for a retrace to happen.
  1515.   sti
  1516.   mov dx,input1Port
  1517. @@L:
  1518.   in al,dx          ;this also resets attribute controller flip/flop
  1519.   test al,8
  1520.   jz @@L            ;wait for vertical retrace
  1521.   mov dx,attrPort
  1522.   mov al,33h
  1523.   cli
  1524.   out dx,al         ;select Pixel Pan reg
  1525.   and cl,3
  1526.   mov al,cl
  1527.   shl al,1          ;for 256 color mode
  1528.   out dx,ax
  1529.   sti
  1530.   ret
  1531.   endp
  1532.  
  1533.  
  1534. public waitRetrace
  1535.  
  1536. proc waitRetrace far
  1537.   mov dx,input1Port
  1538. @@L1:
  1539.   in al,dx
  1540.   test al,8
  1541.   jnz @@L1 ;wait for no v retrace
  1542. @@L2:
  1543.   in al,dx
  1544.   test al,8
  1545.   jz @@L2  ;wait for v retrace
  1546.   ret
  1547.   endp
  1548.  
  1549.  
  1550. ;--------------------------------------------------------------------
  1551.  
  1552. ;sets up the specified version of Mode X.  Allows for a virtual screen which
  1553. ;can be larger than the displayed screen (which can then be scrolled)
  1554. ;max scroll-to coord is (lxRes-xRes, lyRes-yRes)
  1555.  
  1556. public setModeX
  1557.  
  1558. proc setModeX far tblX:dword,tblY:dword,logX:word,logY:word ;returns boolean in al
  1559.   mov ah,0Fh
  1560.   int 10h
  1561.   mov [oldMode],al   ;save old Gr mode
  1562.   mov ax,1A00h
  1563.   int 10h            ;check for VGA
  1564.   cmp al,1Ah
  1565.   jne @@BADMODE      ;no VGA Bios
  1566.   cmp bl,7
  1567.   jb @@BADMODE       ;is VGA or better?
  1568.   cmp bl,0FFh
  1569.   je @@BADMODE
  1570.   les si,[tblX]      ;mode horiz info table ptr
  1571.   mov ax,[es:si]
  1572.   mov [xRes],ax
  1573.   mov cx,[logX]
  1574.   and cx,0FFF8h
  1575.   cmp cx,ax         ;lxRes must be >=xRes
  1576.   jae @@XOK
  1577.     mov cx,ax
  1578.   @@XOK:
  1579.   mov [lXRes],cx
  1580.   mov di,cx
  1581.   shr di,2
  1582.   mov [lxBytes],di
  1583.   les si,[tblY]
  1584.   mov dx,[es:si]
  1585.   mov [yRes],dx
  1586.   mov bx,[logY]     ;mode vert info table ptr
  1587.   cmp bx,dx         ;lyRes must be >=yRes
  1588.   jae @@YOK
  1589.     mov bx,dx
  1590.   @@YOK:
  1591.   mov [lYRes],bx
  1592.   mov ax,di
  1593.   mul bx            ;calculate needed bytes (lxBytes*lyRes). Must be <=$10000
  1594.   mov [pgBytes],ax
  1595.   sub ax,1          ;subtract 1 for easy compare
  1596.   sbb dx,0
  1597.   jnz @@BADMODE
  1598.  
  1599.   mov ax,13h
  1600.   int 10h                 ;start with mode 13h
  1601.   mov dx,seqPort
  1602.   mov ax,0604h
  1603.   out dx,ax               ;disable Chain 4 mode
  1604.   mov ax,0100h
  1605.   out dx,ax               ;asynchronous reset
  1606.   mov dx,miscOutPort
  1607.   mov ax,[es:si+2]        ;put Dot Clock and Lines/Polarity bytes together
  1608.   les si,[tblX]
  1609.   or ax,[es:si+2]
  1610.   out dx,al               ;send them to Misc Output Reg to set Timing/Size
  1611.   mov dx,seqPort
  1612.   mov ax,0300h
  1613.   out dx,ax               ;restart Sequencer
  1614.  
  1615.   mov dx,CRTCPort         ;un-write protect regs 0~7
  1616.   mov al,11h
  1617.   out dx,al
  1618.   inc dx
  1619.   in al,dx
  1620.   and al,7Fh
  1621.   out dx,al
  1622.   dec dx
  1623.  
  1624.   mov ax,0014h            ;turn off dword mode
  1625.   out dx,ax
  1626.   jmp $+2
  1627.   mov ax,0E317h           ;turn on byte mode
  1628.   out dx,ax
  1629.  
  1630.   ;Now we're in unchained 256-color mode. All that's left is to set the screen size!
  1631.  
  1632.   add si,4                ;now send table of horiz CRTC values/regs to the CRTC port
  1633.   db 0A8h                 ;test al,imm8 instr to skip next 1-byte instr
  1634.   @@L:
  1635.     out dx,ax
  1636.     lods [word es:si]
  1637.     test ax,ax
  1638.     jnz @@L
  1639.   les si,[tblY]
  1640.   add si,4                ;now send table of vert CRTC values/regs to the CRTC port
  1641.   db 0A8h                 ;test al,imm8 instr to skip next 1-byte instr
  1642.   @@L2:
  1643.     out dx,ax
  1644.     lods [word es:si]
  1645.     test ax,ax
  1646.     jnz @@L2
  1647.  
  1648.   mov ax,[lXBytes]
  1649.   shr ax,1             ;Offset Value = lXBytes / 2
  1650.   mov ah,al            ;Switch format for out
  1651.   mov al,13h           ;CRTC Offset Register Index
  1652.   out dx,ax            ;Set VGA CRTC Offset Reg
  1653.  
  1654.   mov [word low pgStart],0
  1655.   mov [word low pgShown],0
  1656.   mov ax,[segA000]
  1657.   mov [word high pgStart],ax
  1658.   mov [word high pgShown],ax
  1659.  
  1660.   push 0
  1661.   call clear           ;clear the screen
  1662.  
  1663.   mov di,offset yTab   ;now make a fast lookup table for scan lines
  1664.   push ds
  1665.   pop es
  1666.   mov ax,0
  1667.   mov bx,[lxBytes]
  1668.   mov cx,[lyRes]
  1669.   @@MAKETAB:
  1670.     stosw
  1671.     add ax,bx
  1672.     dec cx
  1673.     jnz @@MAKETAB
  1674.  
  1675.   mov al,1            ;mode set successfully!
  1676.   db 0A9h             ;test ax,imm16 instr to skip next 2-byte instr
  1677. @@BADMODE:            ;this is obviously either not a color vga
  1678.   xor ax,ax           ;or the logical dimensions were too big.
  1679.   ret
  1680.   endp
  1681.  
  1682.  
  1683. public setText
  1684.  
  1685. proc setText far
  1686.   mov al,[oldMode]
  1687.   mov ah,0
  1688.   int 10h
  1689.   ret
  1690.   endp
  1691.  
  1692.  
  1693. ends
  1694. end
  1695.